
#pragma once

#include "../ql/error.h"
#include "../qlrules/error.h"

static INLINE const char * get_err_text( ErrResult err )
{
    switch( err )
    {
#undef QL_ERROR_DEF
#define QL_ERROR_DEF( e ) case e: return #e;
#include "../ql/error_defs.h"
#include "../qlrules/error_defs.h"
#undef QL_ERROR_DEF
    }
    return "???";
}

static int ask_yesno( const char * ask_text )
{
    for( ;; )
    {
        char buf[4] = { 0 };

        // FIXME: if this line will be removed, we'll not be able to
        // skip redundant '\n' key
        getchar();

        fputc( '\n', stderr );
        fputs( ask_text, stderr );
        fputc( '\n', stderr );
        fputs( "Please, answer yes or no: ", stderr );

        fgets( buf, 4, stdin );

        switch( buf[0] )
        {
        case 'Y': case 'y':
            return 0;

        case 'N': case 'n':
            return 1;
        }
    }
}

static void
rp_err_callback( EvalContext * eval )
{
    ErrResult err = get_evaluator_last_error( eval );
    fprintf( stderr, "Error(%p): %s\n", eval, get_err_text(err) );
}

static void
launch_evaluator_loop_from_stdin( EvalContext * eval )
{
    ReaderContext * reader = create_reader(
        get_evaluator_allocator(eval), stdin, "<stdin>" );

    set_evaluator_callback( eval, rp_err_callback );

    for( ;; )
    {
        Obj * r_obj;

        fputs( "\n>", stderr );
        r_obj = read_obj( reader );

        if( !r_obj )
        {
            fprintf( stderr,
                "Reader Error: %s\n", get_err_text(reader_get_last_error(reader))
                );
            break;
        }

        r_obj = evaluate( eval, r_obj );
        if( !r_obj )
        {
            ErrResult err = get_evaluator_last_error( eval );
            if( QL_ERR_STOP == err )
            {
                break;
            }

            if( 0 != ask_yesno("Would you like to continue evaluation?") )
            {
                break;
            }
            else
            {
                continue;
            }
        }

        fputs( "\n", stderr );
        print_obj( r_obj, stderr );
    }

    free_reader( reader );
}
